package cn.orangeframe.neon.domain.model;

import cn.orangeframe.neon.domain.entity.Auditable;
import cn.orangeframe.neon.domain.entity.WorkflowDef;
import cn.orangeframe.neon.domain.enums.WorkflowStatus;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 工作流模型类，用于描述一个工作流的基本信息。
 */
@Data
@EqualsAndHashCode(callSuper = true)
public class WorkflowModel extends Auditable {

    /**
     * 工作流的名称
     */
    private String workflowName;
    /**
     * 工作流的版本
     */
    private int workflowVersion;
    /**
     * 工作流的状态
     */
    private WorkflowStatus status = WorkflowStatus.RUNNING;
    /**
     * 工作流开始的时间
     */
    private long startTime;
    /**
     * 工作流结束的时间
     */
    private long endTime;
    /**
     * 工作流的ID
     */
    private String workflowId;
    /**
     * 父工作流的ID
     */
    private String parentWorkflowId;
    /**
     * 父工作流任务的ID
     */
    private String parentWorkflowTaskId;
    /**
     * 工作流中的任务列表
     */
    private List<TaskModel> tasks = new CopyOnWriteArrayList<>();
    /**
     * 工作流输入的数据
     */
    private Map<String, Object> input = new HashMap<>();
    /**
     * 工作流输出 的数据
     */
    private Map<String, Object> output = new HashMap<>();
    /**
     * 工作流的定义
     */
    private WorkflowDef workflowDefinition;
    /**
     * 工作流结束的原因
     */
    private String reasonForInCompletion;

    /**
     * 根据任务引用名称获取任务模型
     * @param refName 任务引用名称
     * @return 任务模型
     */
    public TaskModel getTaskByRefName(String refName) {
        if (refName == null) {
            throw new RuntimeException("refName passed is null.  Check the workflow execution.  For dynamic tasks, make sure referenceTaskName is set to a not null value");
        }
        LinkedList<TaskModel> found = new LinkedList<>();
        for (TaskModel t : tasks) {
            if (t.getTaskReferenceName() == null) {
                throw new RuntimeException("Task " + t.getTaskDefName() + " does not have reference name specified.");
            }
            if (t.getTaskReferenceName().equals(refName)) {
                found.add(t);
            }
        }
        if (found.isEmpty()) {
            return null;
        }
        return found.getLast();
    }

}
